package com.ys.erp.stage_user_service.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.entity.data.bean.User;
import com.ys.erp.entity.data.bean.UserPulse;
import com.ys.erp.entity.data.bean.UserPulseRecord;
import com.ys.erp.entity.service.IEventLogService;
import com.ys.erp.entity.service.IUserPulseRecordService;
import com.ys.erp.entity.service.IUserPulseService;
import com.ys.erp.entity.service.IUserService;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_user_service.bean.condition.UserPulseCondition;
import com.ys.erp.stage_user_service.bean.vo.UserPulseRecordStatisticsVO;
import com.ys.erp.stage_user_service.bean.vo.UserPulseRecordVO;
import com.ys.erp.stage_user_service.utils.PulseNotificationUtil;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@RequiredArgsConstructor
@Service
@RefreshScope
@Log4j
public class UserPulseService {

    private final IUserPulseService iUserPulseService;

    private final IUserPulseRecordService iUserPulseRecordService;

    private final IEventLogService iEventLogService;

    private final IUserService iUserService;

    private final PulseNotificationUtil pulseNotificationUtil;

    /**
     * 分页幺豆记录
     *
     * @param empDto        登录员工
     * @param con           筛选数据
     * @return              分页数据
     */
    public PageDTO<UserPulseRecordVO> pageUserPulseRecord(StageEmpDTO empDto, UserPulseCondition.PageInPulseRecordCon con) {
        //构造条件
        QueryWrapper<UserPulseRecord> recordQw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(con.getUserId())) {
            recordQw.lambda().eq(UserPulseRecord::getUserId, con.getUserId());
        }
        if(ObjectUtils.isNotEmpty(con.getRecordStartDate())) {
            recordQw.lambda().ge(UserPulseRecord::getRecordTime, con.getRecordStartDate()+" 00:00:00");
        }
        if (ObjectUtils.isNotEmpty(con.getRecordEndDate())) {
            recordQw.lambda().le(UserPulseRecord::getRecordTime, con.getRecordEndDate()+" 23:59:59");
        }
        // 类目类型筛选
        if (ObjectUtils.isNotEmpty(con.getInOutType())) {
            recordQw.lambda().eq(UserPulseRecord::getInOutType, con.getInOutType());
        }

        recordQw.lambda().orderByDesc(UserPulseRecord::getId);
        // 创建分页条件
        Page<UserPulseRecord> userPulseRecordPage = new Page<>(con.getCurrent(), con.getSize());
        Page<UserPulseRecord> page = iUserPulseRecordService.page(userPulseRecordPage, recordQw);

        // 判断page.record是否为空，如果为空直接返回
        if (page.getRecords().isEmpty()) {
            return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        ArrayList<UserPulseRecordVO> results = new ArrayList<>();
        for (UserPulseRecord record : page.getRecords()) {
            UserPulseRecordVO vo = new UserPulseRecordVO();
            vo.setUserId(record.getUserId());
            vo.setRecordDate(record.getRecordTime());
            vo.setRecordInOutType(record.getInOutType());
            vo.setRecordMoney(MoneyUtil.long2Str(record.getRecordNum()));
            vo.setRecordRemark(record.getRemark());
            vo.setRecordRelaNo(record.getRelaNo());
            vo.setRecordType(record.getRecordType());
            results.add(vo);
        }
        //将集合设置到PageDTO里面，返回
        return new PageDTO<>(page.getCurrent(), page.getTotal(), results);
    }

    /**
     * 统计幺豆使用
     *
     * @param empDto                登录员工
     * @param con                   请求体
     * @return                      统计数据
     */
    public UserPulseRecordStatisticsVO pageUserPulseStatistics(StageEmpDTO empDto, UserPulseCondition.@Valid PageInPulseRecordCon con) {
        //查询全部用户
        QueryWrapper<UserPulse> userPulseQw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(con.getUserId())) {
            userPulseQw.lambda().eq(UserPulse::getUserId, con.getUserId());
        }
        List<UserPulse> userPulses = iUserPulseService.list(userPulseQw);
        //计算用户剩余金额
        long totalMoney = 0L;
        for (UserPulse userPulse : userPulses) {
            totalMoney += userPulse.getPulseNum();
        }

        //累计剩余幺豆余额
        String moneyCount = MoneyUtil.long2Str(totalMoney);
        PageDTO<UserPulseRecordVO> userPulseRecordVOPageDTO = pageUserPulseRecord(empDto, con);

        //总计赠送余额
        long inMoneyTotal = 0L;
        long outMoneyTotal = 0L;
        // 添加空值判断
        for(UserPulseRecordVO userPulseRecordVO : userPulseRecordVOPageDTO.getRecords()) {
            String recordType = userPulseRecordVO.getRecordType();
            String recordMoney = userPulseRecordVO.getRecordMoney();
            // 空值检查
            if (recordType == null || recordMoney == null) {
                continue;  // 跳过无效记录
            }
            long money = MoneyUtil.str2Long(recordMoney);
            if (recordType.equals(UserPulseRecord.Enums.IN.name())) {
                inMoneyTotal += money;
            } else {
                outMoneyTotal += money;
            }
        }
        //包装进返回对象内返回
        UserPulseRecordStatisticsVO userPulseRecordStatisticsVO = new UserPulseRecordStatisticsVO();
        userPulseRecordStatisticsVO.setYDRemaining(moneyCount);
        userPulseRecordStatisticsVO.setYDUse(MoneyUtil.long2Str(outMoneyTotal));
        userPulseRecordStatisticsVO.setYDGift(MoneyUtil.long2Str(inMoneyTotal));
        // 返回包装统计数据包装对象
        //public 返回类型 方法名称(参数){方法逻辑}
        return userPulseRecordStatisticsVO;
    }
    /**
     * 充值用户幺豆
     *
     * @param empDto            登录员工
     * @param con               请求体
     */
    @Transactional(rollbackFor = Exception.class)
    public void inUserPulse(StageEmpDTO empDto, UserPulseCondition.InOrOutUserPulseCon con) {
        QueryWrapper<UserPulse> userPulseQw = new QueryWrapper<>();
        userPulseQw.lambda().eq(UserPulse::getUserId, con.getUserId());
        userPulseQw.lambda().last(" for update");
        UserPulse userPulse = iUserPulseService.getOne(userPulseQw);
        if (ObjectUtils.isEmpty(userPulse)) {
            userPulse = new UserPulse();
            userPulse.setUserId(con.getUserId());
            userPulse.setPulseNo(userPulse.getRandOrderNo());
            userPulse.setPulseNum(0L);
        }
        Long oldMoney = userPulse.getPulseNum();
        userPulse.setPulseNum(userPulse.getPulseNum() + MoneyUtil.str2Long(con.getMoney()));
        iUserPulseService.saveOrUpdate(userPulse);
        //创建充值记录
        LocalDateTime now = LocalDateTime.now();
        UserPulseRecord pulseRecord = new UserPulseRecord();
        pulseRecord.setUserId(con.getUserId());
        pulseRecord.setPulseNo(userPulse.getPulseNo());
        pulseRecord.setRecordType(UserPulseRecord.Enums.IN.name());
        pulseRecord.setInOutType(UserPulseRecord.Enums.EMP_ADD.name());
        pulseRecord.setRecordNum(MoneyUtil.str2Long(con.getMoney()));
        pulseRecord.setEmpId(empDto.getId());
        pulseRecord.setEmpName(empDto.getRealName());
        pulseRecord.setRecordTime(now);
        pulseRecord.setRemark(con.getRemark());
        iUserPulseRecordService.save(pulseRecord);
        //增加日志
        iEventLogService.insertEvent(empDto, "充值用户" + con.getUserId() + "幺豆：" + con.getMoney(), pulseRecord.getId(), EnableEnum.YES.getEnable(), JSONObject.toJSONString(con));
        
        // 发送幺豆充值通知
        try {
            User user = iUserService.getById(con.getUserId());
            if (ObjectUtils.isNotEmpty(user) && ObjectUtils.isNotEmpty(user.getOpenId())) {
                pulseNotificationUtil.sendPulseRechargeNotification(user, con.getMoney(), userPulse.getPulseNum(), empDto.getRealName(), con.getRemark());
            }
        } catch (Exception e) {
            log.error("发送幺豆充值通知失败，用户ID：" + con.getUserId(), e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void outUserPulse(StageEmpDTO empDto, UserPulseCondition.InOrOutUserPulseCon con) {
        QueryWrapper<UserPulse> userPulseQw = new QueryWrapper<>();
        userPulseQw.lambda().eq(UserPulse::getUserId, con.getUserId());
        userPulseQw.lambda().last(" for update");
        UserPulse userPulse = iUserPulseService.getOne(userPulseQw);
        if (ObjectUtils.isEmpty(userPulse)) {
            userPulse = new UserPulse();
            userPulse.setUserId(con.getUserId());
            userPulse.setPulseNo(userPulse.getRandOrderNo());
            userPulse.setPulseNum(0L);
            iUserPulseService.save(userPulse);
            return;
        }
        Long outMoney = MoneyUtil.str2Long(con.getMoney());
        if (outMoney > userPulse.getPulseNum()) {
            outMoney = userPulse.getPulseNum();
        }
        userPulse.setPulseNum(userPulse.getPulseNum() - outMoney);
        iUserPulseService.updateById(userPulse);
        //创建充值记录
        LocalDateTime now = LocalDateTime.now();
        UserPulseRecord pulseRecord = new UserPulseRecord();
        pulseRecord.setUserId(con.getUserId());
        pulseRecord.setPulseNo(userPulse.getPulseNo());
        pulseRecord.setRecordType(UserPulseRecord.Enums.OUT.name());
        pulseRecord.setInOutType(UserPulseRecord.Enums.EMP_REDUCE.name());
        pulseRecord.setRecordNum(outMoney);
        pulseRecord.setEmpId(empDto.getId());
        pulseRecord.setEmpName(empDto.getRealName());
        pulseRecord.setRecordTime(now);
        pulseRecord.setRemark(con.getRemark());
        iUserPulseRecordService.save(pulseRecord);
        //增加日志
        iEventLogService.insertEvent(empDto, "扣除用户" + con.getUserId() + "幺豆：" + con.getMoney(), pulseRecord.getId(), EnableEnum.YES.getEnable(), JSONObject.toJSONString(con));
    }

}
